﻿using MiniFox.Caching.Configurations;
using MiniFox.Configurations;
using System;
using System.Globalization;
using System.Reflection;

namespace MiniFox.Caching
{
    /// <summary>
    /// 缓存服务
    /// </summary>
    public static class CacheService
    {
        static CacheProvider _defaultCacheProvider;
        static readonly object _locker;

        /// <summary>
        /// 
        /// </summary>
        static CacheService()
        {
            _locker = new object();
        }
        /// <summary>
        /// 
        /// </summary>
        internal static CacheConfiguration CacheConfig
        {
            get
            {
                return ConfigurationFactory.GetConfig<CacheConfiguration>();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static CacheProvider GetCacheProvider()
        {
            return GetCacheProvider(string.Empty);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static CacheProvider GetCacheProvider(string name)
        {
            if (CacheConfig == null)
                return new DefaultCacheProvider();
            if (string.IsNullOrWhiteSpace(CacheConfig.DefaultProvider) && string.IsNullOrWhiteSpace(name))
                return new DefaultCacheProvider();

            name = string.IsNullOrWhiteSpace(name) ? CacheConfig.DefaultProvider : name;
            CacheProviderSetting setting = CacheConfig.CacheSettings[name];
            if (string.IsNullOrEmpty(setting.TypeName))
            {
                return new DefaultCacheProvider(setting.Prefix, setting.Suffix, setting.Expired);
            }
            object instance = setting.CreateInstance(setting.Prefix, setting.Suffix, setting.Expired);
            CacheProvider cacheProvider = instance as CacheProvider;
            return cacheProvider;
        }
        /// <summary>
        /// 获取缓存提供者对象
        /// </summary>
        public static CacheProvider DefaultCachingProvider
        {
            get
            {
                lock (_locker)
                {
                    if (_defaultCacheProvider == null)
                    {
                        try
                        {
                            _defaultCacheProvider = GetCacheProvider();
                        }
                        catch
                        {
                            _defaultCacheProvider = new DefaultCacheProvider();
                        }
                    }
                }
                return _defaultCacheProvider;
            }
        }
        /// <summary>
        /// 根据指定的键添加一个对象到缓存
        /// </summary>
        /// <param name="key"></param>
        /// <param name="val"></param>
        public static void AddCacheObject(string key, object val)
        {
            DefaultCachingProvider.Add(key, val);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool Contains(string key)
        {
            return DefaultCachingProvider.Contains(key);
        }

        /// <summary>
        /// 根据指定的键添加一个对象到缓存
        /// </summary>
        /// <param name="key">键名</param>
        /// <param name="val">缓存对象</param>
        /// <param name="durationSeconds">过期时长(单位: 秒)</param>
        public static void AddCacheObject(string key, object val, int durationSeconds)
        {
            DefaultCachingProvider.Add(key, val, durationSeconds);
        }
        /// <summary>
        /// 根据指定的键获取缓存中的对象
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static object GetCacheObject(string key)
        {
            return DefaultCachingProvider.Get(key);
        }
        /// <summary>
        /// 根据指定的键获取缓存中的对象
        /// </summary>
        /// <param name="key"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        public static object GetCacheObject(string key, Func<object> func)
        {
            return DefaultCachingProvider.Get(key, func);
        }
        /// <summary>
        /// 根据指定的键获取缓存中的对象
        /// </summary>
        /// <param name="key"></param>
        /// <param name="func"></param>
        /// <param name="durationSeconds"></param>
        /// <returns></returns>
        public static object GetCacheObject(string key, Func<object> func, int durationSeconds)
        {
            return DefaultCachingProvider.Get(key, func, durationSeconds);
        }
        /// <summary>
        /// 根据指定的键获取缓存中的对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static T GetCacheObject<T>(string key)
        {
            return DefaultCachingProvider.Get<T>(key);
        }
        /// <summary>
        /// 根据指定的键获取缓存中的对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        public static T GetCacheObject<T>(string key, Func<T> func)
        {
            return DefaultCachingProvider.Get<T>(key, func);
        }
        /// <summary>
        /// 根据指定的键获取缓存中的对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="func"></param>
        /// <param name="durationSeconds"></param>
        /// <returns></returns>
        public static T GetCacheObject<T>(string key, Func<T> func, int durationSeconds)
        {
            return DefaultCachingProvider.Get<T>(key, func, durationSeconds);
        }
        /// <summary>
        /// 根据指定的键移除缓存中的对象
        /// </summary>
        /// <param name="key"></param>
        public static void RemoveObject(string key)
        {
            DefaultCachingProvider.Remove(key);
        }
        /// <summary>
        /// 清除缓存中所有对象
        /// </summary>
        public static void Clear()
        {
            DefaultCachingProvider.RemoveAll();
        }
        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="pair"></param>
        ///// <param name="dataProvider"></param>
        ///// <returns></returns>
        //public static DataTable GetCacheData(KeyValuePair<string, IDataQuery> pair, IDataProvider dataProvider)
        //{
        //    DataTable table = CachingProvider.Get<DataTable>(pair.Key) as DataTable; // HttpRuntime.Cache[pair.Key] as DataTable;

        //    lock (typeof(CacheService))
        //    {
        //        if (table == null)
        //        {
        //            try
        //            {
        //                table = dataProvider.ExecuteQuery(pair.Value);

        //                CachingProvider.Add(pair.Key, table);

        //                //SqlCacheDependency dependency = dataProvider.CreateSqlCacheDependency(pair.Value, table);
        //                //HttpRuntime.Cache.Insert(pair.Key, table, dependency, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration);
        //            }
        //            catch
        //            {
        //            }
        //        }
        //    }
        //    return table;
        //}
        ///// <summary>
        ///// 
        ///// </summary>
        ///// <typeparam name="T"></typeparam>
        ///// <returns></returns>
        //public static IEnumerable<T> GetCacheData<T>() where T : class, IEntity
        //{
        //    Type type = typeof(T);
        //    IEnumerable<T> list = CachingProvider.Get<IEnumerable<T>>(type.FullName) as IEnumerable<T>;

        //    lock (typeof(CacheService))
        //    {
        //        if (list == null)
        //        {
        //            try
        //            {
        //                CacheProviderSetting setting = CacheConfig.CacheSettings[type.FullName];
        //                string dataProviderName = setting.DataProviderName;
        //                string connectionString = ConfigurationManager.ConnectionStrings[dataProviderName].ConnectionString;
        //                long expired = setting.Expired;
        //                /************/
        //                IDataProvider dataProvider = DataProviderFactory.GetDataProvider(dataProviderName);
        //                list = dataProvider.LoadEntities<T>();
        //                /************/

        //                CachingProvider.Add(type.FullName, list, expired);

        //                //TableMapping tableMapping = TableMapping.GetTableMapping<T>();
        //                //string[] tables = SqlCacheDependencyAdmin.GetTablesEnabledForNotifications(connectionString);

        //                //if (!tables.Contains(tableMapping.SourceTable))
        //                //    SqlCacheDependencyAdmin.EnableTableForNotifications(connectionString, tableMapping.SourceTable);
        //                //SqlCacheDependency dependency = dataProvider.CreateSqlCacheDependency<T>();// new SqlCacheDependency(dataProviderName, tableMapping.SourceTable);
        //                //HttpRuntime.Cache.Insert(type.FullName, list, dependency, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration);
        //            }
        //            catch
        //            {
        //            }
        //        }
        //    }
        //    return list;
        //}

    }
}
